# -*- coding: utf-8 -*-
"""
心理咨询师服务系统 - 用户模型
"""

from datetime import datetime, timedelta
from werkzeug.security import generate_password_hash, check_password_hash
from flask_jwt_extended import create_access_token, create_refresh_token
from sqlalchemy import Numeric
from app import db
from .base import BaseModel


class User(BaseModel):
    """用户表"""
    
    __tablename__ = 'users'
    
    # 基本信息
    username = db.Column(db.String(80), unique=True, nullable=False, comment='用户名')
    email = db.Column(db.String(120), unique=True, nullable=False, comment='邮箱')
    phone = db.Column(db.String(20), unique=True, nullable=True, comment='手机号')
    password_hash = db.Column(db.String(255), nullable=False, comment='密码哈希')
    
    # 状态信息
    is_active = db.Column(db.Boolean, default=True, nullable=False, comment='是否激活')
    is_verified = db.Column(db.Boolean, default=False, nullable=False, comment='是否验证')
    last_login_at = db.Column(db.DateTime, comment='最后登录时间')
    login_count = db.Column(db.Integer, default=0, comment='登录次数')
    
    # 统计信息
    assessment_count = db.Column(db.Integer, default=0, comment='测评次数')
    
    # 关联关系
    membership = db.relationship('UserMembership', back_populates='user', uselist=False, cascade='all, delete-orphan')
    basic_info = db.relationship('UserBasicInfo', back_populates='user', cascade='all, delete-orphan')
    agreement_confirmations = db.relationship('UserAgreementConfirmation', back_populates='user', cascade='all, delete-orphan')
    assessments = db.relationship('Assessment', back_populates='user', cascade='all, delete-orphan')
    
    def set_password(self, password):
        """设置密码"""
        self.password_hash = generate_password_hash(password)
    
    def check_password(self, password):
        """验证密码"""
        return check_password_hash(self.password_hash, password)
    
    def generate_tokens(self):
        """生成JWT令牌"""
        access_token = create_access_token(
            identity=str(self.id),
            additional_claims={'type': 'user'}
        )
        refresh_token = create_refresh_token(identity=str(self.id))
        return access_token, refresh_token
    
    def update_login_info(self):
        """更新登录信息"""
        self.last_login_at = datetime.utcnow()
        self.login_count += 1
        db.session.commit()
    
    def get_membership_type(self):
        """获取会员类型"""
        if self.membership and self.membership.is_member_active():
            return self.membership.member_type
        return 'basic'
    
    def can_assess(self):
        """检查是否可以进行测评"""
        membership_type = self.get_membership_type()
        
        # 基础会员限制
        if membership_type == 'basic':
            # 检查本月测评次数
            from config import Config
            limit = Config.MEMBER_LIMITS['basic']['assessments_per_month']
            
            # 计算本月测评次数
            now = datetime.utcnow()
            month_start = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
            month_assessments = Assessment.query.filter(
                Assessment.user_id == self.id,
                Assessment.created_at >= month_start
            ).count()
            
            return month_assessments < limit
        
        # 其他会员类型无限制或有更高限制
        return True
    
    def get_basic_info(self, field_name, default=None):
        """获取基础信息字段值"""
        info = UserBasicInfo.query.filter_by(
            user_id=self.id, 
            field_name=field_name
        ).first()
        return info.field_value if info else default
    
    def set_basic_info(self, field_name, value):
        """设置基础信息字段值"""
        info = UserBasicInfo.query.filter_by(
            user_id=self.id, 
            field_name=field_name
        ).first()
        
        if info:
            info.field_value = str(value) if value is not None else None
        else:
            info = UserBasicInfo(
                user_id=self.id,
                field_name=field_name,
                field_value=str(value) if value is not None else None
            )
            db.session.add(info)
    
    @property
    def avatar(self):
        """获取头像URL"""
        return self.get_basic_info('avatar')
    
    @property
    def real_name(self):
        """获取真实姓名"""
        return self.get_basic_info('real_name')
    
    @property
    def gender(self):
        """获取性别"""
        return self.get_basic_info('gender')
    
    @property
    def birth_date(self):
        """获取出生日期"""
        birth_date_str = self.get_basic_info('birth_date')
        if birth_date_str:
            try:
                from datetime import datetime
                return datetime.strptime(birth_date_str, '%Y-%m-%d').date()
            except ValueError:
                return None
        return None
    
    @property
    def profession(self):
        """获取职业"""
        return self.get_basic_info('profession')
    
    @property
    def education(self):
        """获取学历"""
        return self.get_basic_info('education')
    
    @property
    def bio(self):
        """获取个人简介"""
        return self.get_basic_info('bio')

    def to_dict(self, exclude=None, include_relationships=False):
        """转换为字典，排除敏感信息"""
        exclude = exclude or []
        exclude.extend(['password_hash'])
        
        # 获取基本字段
        result = super().to_dict(exclude=exclude, include_relationships=include_relationships)
        
        # 添加基础信息字段
        basic_fields = ['avatar', 'real_name', 'gender', 'birth_date', 'profession', 'education', 'bio']
        for field in basic_fields:
            result[field] = getattr(self, field)
        
        # 添加会员信息显示名称
        if include_relationships and self.membership:
            membership_data = result.get('membership', {})
            if isinstance(membership_data, dict):
                plan_type_map = {
                    'basic': '基础会员',
                    'professional': '专业会员',
                    'institution': '机构会员',
                    'research': '科研会员'
                }
                membership_data['plan_type_display'] = plan_type_map.get(
                    membership_data.get('plan_type'), '基础会员'
                )
                result['membership'] = membership_data
        
        return result
    
    def __repr__(self):
        return f'<User {self.username}>'


class UserMembership(BaseModel):
    """用户会员信息表"""
    
    __tablename__ = 'user_memberships'
    
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False, unique=True, comment='用户ID')
    plan_type = db.Column(
        db.Enum('basic', 'professional', 'institution', 'research', name='plan_type'),
        nullable=False,
        default='basic',
        comment='会员类型'
    )
    start_date = db.Column(db.Date, comment='开始时间')
    end_date = db.Column(db.Date, comment='结束时间')
    status = db.Column(
        db.Enum('active', 'expired', 'cancelled', name='membership_status'),
        nullable=False,
        default='active',
        comment='状态'
    )
    custom_scale_limit = db.Column(db.Integer, default=0, comment='自定义量表限制')
    result_display_type = db.Column(
        db.Enum('full', 'simple', 'score_only', name='result_display_type'),
        default='full',
        comment='结果显示类型'
    )
    payment_amount = db.Column(Numeric(10, 2), default=0.00, comment='支付金额')
    payment_method = db.Column(db.String(50), comment='支付方式')
    
    # 关联关系
    user = db.relationship('User', back_populates='membership')
    
    @property
    def member_type(self):
        """为了向后兼容，提供member_type属性"""
        return self.plan_type
    
    @member_type.setter
    def member_type(self, value):
        """为了向后兼容，提供member_type设置器"""
        self.plan_type = value
    
    @property
    def is_active(self):
        """为了向后兼容，检查会员是否有效"""
        return self.status == 'active'
    
    @property
    def expires_at(self):
        """为了向后兼容，将end_date转换为datetime"""
        if self.end_date:
            from datetime import datetime, time
            return datetime.combine(self.end_date, time.max)
        return None
    
    @property
    def activated_at(self):
        """为了向后兼容，将start_date转换为datetime"""
        if self.start_date:
            from datetime import datetime, time
            return datetime.combine(self.start_date, time.min)
        return None
    
    def is_member_active(self):
        """检查会员是否有效"""
        if self.status != 'active':
            return False
        
        if self.end_date:
            from datetime import date
            return date.today() <= self.end_date
        
        return True
    
    def days_remaining(self):
        """剩余天数"""
        if not self.end_date:
            return None
        
        from datetime import date
        remaining = self.end_date - date.today()
        return remaining.days if remaining.days > 0 else 0
    
    def get_benefits(self):
        """获取会员权益"""
        benefits = {
            'basic': {
                'max_assessments_per_month': 50,
                'can_create_custom_scales': False,
                'priority_support': False,
                'data_retention_months': 3,
                'available_scales': ['PHQ-9', 'GAD-7'],
                'report_type': 'simple'
            },
            'professional': {
                'max_assessments_per_month': 500,
                'can_create_custom_scales': True,
                'custom_scale_limit': 5,
                'priority_support': True,
                'data_retention_months': 12,
                'available_scales': 'all_standard',
                'report_type': 'full',
                'ai_interpretation': True,
                'validity_check': True
            },
            'institution': {
                'max_assessments_per_month': -1,  # 无限制
                'can_create_custom_scales': True,
                'custom_scale_limit': -1,  # 无限制
                'priority_support': True,
                'data_retention_months': -1,  # 永久
                'available_scales': 'all',
                'report_type': 'all',
                'team_collaboration': True,
                'api_access': True,
                'custom_service': True
            },
            'research': {
                'max_assessments_per_month': -1,  # 无限制
                'can_create_custom_scales': True,
                'custom_scale_limit': -1,  # 无限制
                'priority_support': True,
                'data_retention_months': -1,  # 永久
                'available_scales': 'all_plus_custom',
                'report_type': 'research',
                'statistical_analysis': True,
                'raw_data_export': True,
                'algorithm_customization': True,
                'technical_support': True,
                'custom_norms': True
            }
        }
        
        return benefits.get(self.plan_type, benefits['basic'])
    
    def can_create_custom_scale(self):
        """检查是否可以创建自定义量表"""
        benefits = self.get_benefits()
        return benefits.get('can_create_custom_scales', False)
    
    def to_dict(self, exclude=None, include_relationships=False):
        """转换为字典格式，处理日期类型序列化"""
        exclude = exclude or []
        result = super().to_dict(exclude=exclude, include_relationships=include_relationships)
        
        # 处理日期类型的序列化
        if 'start_date' in result and self.start_date:
            result['start_date'] = self.start_date.isoformat()
        if 'end_date' in result and self.end_date:
            result['end_date'] = self.end_date.isoformat()
        
        return result
    
    def __repr__(self):
        return f'<UserMembership {self.user_id}:{self.plan_type}>'


class UserBasicInfo(BaseModel):
    """用户基础信息表"""
    
    __tablename__ = 'user_basic_info'
    
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=True, comment='用户ID（匿名用户为空）')
    session_id = db.Column(db.String(100), nullable=True, comment='会话ID（匿名用户标识）')
    assessment_id = db.Column(db.Integer, nullable=True, comment='测评记录ID（个人资料信息可为空）')
    field_name = db.Column(db.String(50), nullable=False, comment='字段名称')
    field_value = db.Column(db.Text, comment='字段值')
    
    # 关联关系
    user = db.relationship('User', back_populates='basic_info')
    
    def __repr__(self):
        return f'<UserBasicInfo {self.user_id}:{self.field_name}>'


class UserAgreementConfirmation(BaseModel):
    """用户协议确认记录表"""
    
    __tablename__ = 'user_agreement_confirmations'
    
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False, comment='用户ID')
    agreement_type = db.Column(db.String(50), nullable=False, comment='协议类型')
    agreement_version = db.Column(db.String(20), nullable=False, comment='协议版本')
    confirmed_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow, comment='确认时间')
    ip_address = db.Column(db.String(45), comment='IP地址')
    user_agent = db.Column(db.Text, comment='用户代理')
    
    # 关联关系
    user = db.relationship('User', back_populates='agreement_confirmations')
    
    def __repr__(self):
        return f'<UserAgreementConfirmation {self.user_id}:{self.agreement_type}>'


class MembershipPlan(BaseModel):
    """会员套餐表"""
    
    __tablename__ = 'membership_plans'
    
    name = db.Column(db.String(100), nullable=False, comment='套餐名称')
    description = db.Column(db.Text, comment='套餐描述')
    plan_type = db.Column(
        db.Enum('basic', 'professional', 'institution', 'research', name='plan_type'),
        nullable=False,
        comment='会员类型'
    )
    duration_days = db.Column(db.Integer, nullable=False, comment='有效期天数')
    original_price = db.Column(Numeric(10, 2), nullable=False, comment='原价')
    current_price = db.Column(Numeric(10, 2), nullable=False, comment='现价')
    discount_percentage = db.Column(db.Integer, default=0, comment='折扣百分比')
    features = db.Column(db.JSON, comment='功能特性')
    is_popular = db.Column(db.Boolean, default=False, comment='是否热门')
    is_active = db.Column(db.Boolean, default=True, comment='是否启用')
    sort_order = db.Column(db.Integer, default=0, comment='排序')
    
    @property
    def member_type(self):
        """为了向后兼容，提供member_type属性"""
        return self.plan_type
    
    @member_type.setter
    def member_type(self, value):
        """为了向后兼容，提供member_type设置器"""
        self.plan_type = value
    
    def __repr__(self):
        return f'<MembershipPlan {self.name}>'


class MembershipOrder(BaseModel):
    """会员订单表"""
    
    __tablename__ = 'membership_orders'
    
    order_no = db.Column(db.String(50), unique=True, nullable=False, comment='订单号')
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False, comment='用户ID')
    plan_id = db.Column(db.Integer, db.ForeignKey('membership_plans.id'), nullable=False, comment='套餐ID')
    plan_name = db.Column(db.String(100), nullable=False, comment='套餐名称')
    original_price = db.Column(Numeric(10, 2), nullable=False, comment='原价')
    paid_price = db.Column(Numeric(10, 2), nullable=False, comment='实付金额')
    payment_method = db.Column(db.String(50), comment='支付方式')
    status = db.Column(
        db.Enum('pending', 'paid', 'cancelled', 'refunded', name='order_status'),
        default='pending',
        nullable=False,
        comment='订单状态'
    )
    paid_at = db.Column(db.DateTime, comment='支付时间')
    cancelled_at = db.Column(db.DateTime, comment='取消时间')
    refunded_at = db.Column(db.DateTime, comment='退款时间')
    
    # 关联关系
    user = db.relationship('User', backref='membership_orders')
    plan = db.relationship('MembershipPlan', backref='orders')
    
    def __repr__(self):
        return f'<MembershipOrder {self.order_no}>'